import { PositionHelper } from "utils/position/PositionHelper";
import { ABaseEntity } from "../BaseEntity";
import { AllEntityTypes, EntityType } from "../Entity.interface";
import { MemoryManager } from "GameLoop/DecisionMaking/MemoryManager";
import { CoreLayout, CoreLayoutConfig } from "./core/corelayout";
import { cache_return, cache_return_Constant, cpu_used } from "utils/decorate/decorate";
import { CacheDataStructure } from "GameLoop/WorldState/PollingStation/PollingTasks/RoomItem/CacheStructure";
 
export function entity_memory_cache():any
{
    return function(target:any, propertyname: string)
    {
        Object.defineProperty(target, propertyname, {
            get(): unknown {
                return this.getNodeMemory()[propertyname];
            },
            set(newValue: unknown) {
                this.getNodeMemory()[propertyname]= newValue;
            },
            enumerable: true
          });
    }
}
export abstract  class StructureEntity< T extends INoMemory,V extends IRoomModuleInitializer=IRoomModuleInitializer > extends ABaseEntity< T,V >
{
   
    // ModulePlan!:IModulePlan; // plan
    protected _basepos!:RoomPosition;
    protected _cahcheStation!:CacheDataStructure<ICacheStructure<StructureConstant>>
    public get BasePosition()
    {
        return this._basepos;
    }
  
    public  get roomName()
    {
        return this._initializer.roomName;
    }
    public get room():Required<Room>
    {
        return Game.rooms[this.roomName] as Required<Room>
    }
    public get lordRoom()
    {
        return Game.rooms[ Memory.rooms[this.roomName].lord] as Required<Room>
       
    }
    public get region():string{
        return this.roomName
    }
    // @cpu_used()
    public   getNodeMemory (): T {
        const regionCache = MemoryManager.getMemory<IMemoryCache>(this.region);
        if(!regionCache.Nodes ||!regionCache.Nodes[this.key])
        {
            global.Log.Error(`${this.GUID}->${this.entityType()} 的内存未初始化`)
            // throw new Error(`${this.GUID}->${this.entityType()} 的内存未初始化`)
        }
        return regionCache.Nodes[this.key]
    }
    public initAttributes(): void {
        this.initNodeMemory();
        console.log(`初始化属性:${ JSON.stringify(this.GUID())}`)
        const p = this._initializer.plan?.pos;
       
        if(p)
        {
            this._basepos = PositionHelper.New( p.x,p.y,this.roomName)
        }
        else
        {
            this._basepos = new RoomPosition(0,0,this.roomName);
        }
        
        this._cahcheStation = global.world.PollStructure(this.roomName) as any;
    }

    public abstract updateMemory():void;
    protected initNodeMemory()
    {
        const regionCache = MemoryManager.getMemory<IMemoryCache>(this.region);
        if(!regionCache)
        {
            this.log('error', `找不到内存`,this.region);
        }
        if(!regionCache.Nodes)
        {
            regionCache.Nodes={};
             
        }
        if(!regionCache.Nodes[this.key])
        {
            regionCache.Nodes[this.key]={};
        }
    }
    // public  findRegionTaskById<T>(id: string, region: string =this.region): T 
    // {
    //     //  this.room.fin
    // }
    /**
     * 根据相对位置偏移查询建筑
     * @param type 
     * @param poss 
     * @param base 
     * @returns 
     */
    // @cpu_used((action:any)=>{
    //     return `相对坐标建筑缓存测试`
    // },
    // (...arg:any[])=>
    // {
    //     return   arg[3]>1
    // },
    // (text,type,poss)=>
    // {
    //     console.log(text,`错误缓存读取数据超过1cpu`,`[${poss.length}]`)
    // }
    // )
    public getStructuresByRelative<T extends StructureConstant>(type:T,poss:IFVector2[],base:IRoomPosition)
    {
        //return poss.map(e=>this.getStructureByRelative(type,e,base))
        return this.getStructures(type,_.map(poss,e=>PositionHelper.addPosition(base,e)))
    }
    // @cache_return_Constant((methodName:string,type:string,p:IFVector2)=>
    // {
    //     return `${methodName}_${type}_${p.x}_${p.y}`
    // })
    public getStructureByRelative<T extends StructureConstant>(type:T,e:IFVector2,base:IRoomPosition)
    {
        return this.getStructure(type,PositionHelper.addPosition(base,e))
    }
    /**
     * 查询缓存获取建筑的ID
     * @param type 
     * @param poss 
     * @returns 
     */
    @cpu_used((action:any)=>{
        return `建筑缓存测试`
    },
    (...arg:any[])=>
    {
        return   arg[2]>1
    },
    (text,type)=>
    {
        console.log(text,`错误缓存读取数据超过1cpu`)
    }
    )
    public getStructures<T extends StructureConstant>(type:T,poss:IRoomPosition[]):Id<ConcreteStructure<T>>[]
    {
        const _this = this;
        let ids:string[]=[];
        for(const e of poss)
        {
            const p = _this.getStructure(type,e);
            if(p)
            {
                ids.push(p.id);
            }
        }
        return ids  as Id<ConcreteStructure<T>>[];
    }

    public getStructureObjects<T extends  Id<_HasId>= Id<_HasId>>(ids:T[],filter?:(s:fromId<T> )=>boolean):fromId<T>[]
    {
        const stores:fromId<T>[]=[];
        if(filter)
        {
            for(const e of ids)            
            {
                const store = Game.getObjectById(e)  as fromId<T>
                if(store && filter(store) )
                {
                    stores.push(store);
                }
            }
        }
        else
        {
            for(const e of ids)            
            {
                const store = Game.getObjectById(e)  as fromId<T>
                if(store )
                {
                    stores.push(store);
                }
            }
        }
        
        return stores
    }

    /**
     * 查询缓存获取建筑的ID
     * @param type 
     * @param poss 
     * @returns 
     */
    public getStructure<T extends StructureConstant>(type:T,pos:IRoomPosition)
    {
        // global.Log.Info(`${JSON.stringify(pos)}`)
       // return Game.rooms[pos.roomName].lookForAt(LOOK_STRUCTURES,pos.x,pos.y).filter(e=>e.structureType == type)[0];
        // 获取建筑ID
        // const cache = global.world.PollStructure(this.roomName);
        // if(cache)
        // {
        //     return  
        // }
        // return undefined
        return this._cahcheStation.lookStructure(type,pos)
    }

    protected getStore(ids:Id<AnyStoreStructure>[],res: IResource,filter:(s:AnyStoreStructure,res:IResource)=>boolean)
    {
        const stores:AnyStoreStructure[]=[];
        for(const e of ids)            
        {
            const store = Game.getObjectById(e) as StructureContainer
            if(store && filter(store,res))
            {
                stores.push(store);
            }
        }
        return stores
    }

    public getAbsulotePosition(p:IFVector2)
    {
        return PositionHelper.addPosition(this.BasePosition,p);
    }
    public getStructuresPos<T extends StructureConstant>(type:T)
    {
        if(this._initializer.plan && this._initializer.plan.structures[type])
        {
            return this._initializer.plan.structures[type].map(e=> this.getAbsulotePosition(e))
        }
        return []
    }
}